package com.hope.hotel.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hope.hotel.common.Result;
import com.hope.hotel.entity.dto.ReviewDTO;
import com.hope.hotel.entity.dto.UserInfoDTO;
import com.hope.hotel.entity.po.Booking;
import com.hope.hotel.entity.po.Review;
import com.hope.hotel.entity.vo.ReviewVO;
import com.hope.hotel.mapper.BookingMapper;
import com.hope.hotel.mapper.ReviewMapper;
import com.hope.hotel.mapper.UserMapper;
import com.hope.hotel.service.ReviewService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 评论服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ReviewServiceImpl extends ServiceImpl<ReviewMapper,Review> implements ReviewService {

    private final ReviewMapper reviewMapper;
    private final BookingMapper bookingMapper;
    private final ObjectMapper objectMapper;
    private final UserMapper userMapper;
    
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    @Transactional
    public Result addReview(ReviewDTO reviewDTO) {
        try {
            // 1. 验证用户是否有权限评论（是否有对应的订单）
            Booking booking = bookingMapper.selectById(reviewDTO.getBookingId());
            if (booking == null) {
                return Result.error("订单不存在");
            }
            
            Long userId = Long.valueOf(reviewDTO.getUserId());
            if (!booking.getUserId().equals(userId)) {
                return Result.error("您无权评价此订单");
            }
            
            // 检查订单状态是否为已完成
            if (!"confirmed".equals(booking.getStatus())) {
                return Result.error("只有已完成的订单才能评价");
            }
            
            // 检查是否已经评价过
            Integer reviewCount = reviewMapper.countBookingReviews(
                Long.valueOf(booking.getBookingId()), userId);
            if (reviewCount > 0) {
                return Result.error("您已经评价过此订单");
            }

            // 用户信息
            UserInfoDTO userInfoDTO = userMapper.selectUserInfo(userId);


            // 2. 保存评论信息
            Review review = new Review();
            review.setUserAvatar(userInfoDTO.getAvatar());
            review.setUserName(userInfoDTO.getUsername());
            review.setReviewId(generateReviewId());
            review.setBookingId(Long.valueOf(booking.getBookingId()));
            review.setHotelId(booking.getHotelId());
            review.setUserId(userId);
            review.setRating(reviewDTO.getRating());
            review.setContent(reviewDTO.getContent());
            
            // 处理照片和标签
            if (reviewDTO.getImages() != null && !reviewDTO.getImages().isEmpty()) {
                review.setPhotos(objectMapper.writeValueAsString(reviewDTO.getImages()));
            }
            
            // 创建默认标签
            List<String> tags = generateTags(reviewDTO);
            review.setTags(objectMapper.writeValueAsString(tags));
            
            review.setCreatedAt(LocalDateTime.now());
            review.setUpdatedAt(LocalDateTime.now());
            review.setStatus(0); // 待回复状态
            
            reviewMapper.insert(review);
            
            // 3. 更新酒店评分（这里需要添加酒店评分计算逻辑）
            // TODO: 实现酒店评分计算和更新
            
            return Result.success(review.getReviewId(), "评论添加成功");
        } catch (Exception e) {
            log.error("添加评论失败", e);
            return Result.error("添加评论失败: " + e.getMessage());
        }
    }

    @Override
    public Result getHotelReviews(String hotelId, int page, int pageSize) {
        try {
            Page<Map<String, Object>> pageParam = new Page<>(page, pageSize);
            IPage<Map<String, Object>> result = reviewMapper.getHotelReviewsPage(
                pageParam, 
                Long.valueOf(hotelId), 
                null, 
                null, 
                null, 
                null
            );
            
            // 转换为ReviewVO
            List<ReviewVO> reviews = new ArrayList<>();
            for (Map<String, Object> record : result.getRecords()) {
                ReviewVO vo = new ReviewVO();
                vo.setId((Long) record.get("review_id"));
                vo.setBookingId((Long) record.get("booking_id"));
                vo.setHotelId((Long) record.get("hotel_id"));
                vo.setUserId((Long) record.get("user_id"));
                vo.setUserName((String) record.get("user_name"));
                vo.setUserAvatar((String) record.get("user_avatar"));
                vo.setRating((Integer) record.get("rating"));
                vo.setContent((String) record.get("content"));
                
                // 处理照片
                String photos = (String) record.get("photos");
                if (photos != null && !photos.isEmpty()) {
                    try {
                        vo.setPhotos(objectMapper.readValue(photos, List.class));
                    } catch (Exception e) {
                        log.error("解析照片失败: {}", e.getMessage());
                        vo.setPhotos(Collections.emptyList());
                    }
                }
                
                // 处理标签
                String tags = (String) record.get("tags");
                if (tags != null && !tags.isEmpty()) {
                    try {
                        vo.setTags(objectMapper.readValue(tags, List.class));
                    } catch (Exception e) {
                        log.error("解析标签失败: {}", e.getMessage());
                        vo.setTags(Collections.emptyList());
                    }
                }
                
                // 处理回复
                vo.setReply((String) record.get("reply"));
                LocalDateTime replyTime = (LocalDateTime) record.get("reply_time");
                if (replyTime != null) {
                    vo.setReplyTime(replyTime);
                    vo.setReplyDate(replyTime.format(DATE_FORMATTER));
                }
                
                // 处理创建时间
                LocalDateTime createdAt = (LocalDateTime) record.get("created_at");
                vo.setCreatedAt(createdAt);
                vo.setDate(createdAt.format(DATE_FORMATTER));
                
                // 设置状态
                Integer status = (Integer) record.get("status");
                vo.setStatus(ReviewVO.getStatusString(status));
                
                reviews.add(vo);
            }
            
            // 构建分页结果
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("records", reviews);
            resultMap.put("total", result.getTotal());
            resultMap.put("pages", result.getPages());
            resultMap.put("current", result.getCurrent());
            resultMap.put("size", result.getSize());
            
            return Result.success(resultMap);
        } catch (Exception e) {
            log.error("获取酒店评论列表失败", e);
            return Result.error("获取酒店评论列表失败: " + e.getMessage());
        }
    }

    @Override
    public Result getUserReviews(String userId) {
        try {
            // 查询用户的所有评论
            LambdaQueryWrapper<Review> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Review::getUserId, Long.valueOf(userId))
                      .ne(Review::getStatus, 3) // 不查询已删除的评论
                      .orderByDesc(Review::getCreatedAt);
            
            List<Review> reviews = reviewMapper.selectList(queryWrapper);
            
            // 转换为ReviewVO
            List<ReviewVO> reviewVOs = new ArrayList<>();
            for (Review review : reviews) {
                ReviewVO vo = convertToReviewVO(review);
                reviewVOs.add(vo);
            }
            
            return Result.success(reviewVOs);
        } catch (Exception e) {
            log.error("获取用户评论列表失败", e);
            return Result.error("获取用户评论列表失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public Result deleteReview(String reviewId, String userId) {
        try {
            // 1. 验证评论是否属于该用户
            Review review = reviewMapper.selectById(reviewId);
            if (review == null) {
                return Result.error("评论不存在");
            }
            
            if (!review.getUserId().toString().equals(userId)) {
                return Result.error("您无权删除此评论");
            }
            
            // 2. 逻辑删除评论（将状态设置为已删除）
            review.setStatus(3); // 已删除
            review.setUpdatedAt(LocalDateTime.now());
            reviewMapper.updateById(review);
            
            // 3. 更新酒店评分
            // TODO: 实现酒店评分更新逻辑
            
            return Result.success("评论删除成功");
        } catch (Exception e) {
            log.error("删除评论失败", e);
            return Result.error("删除评论失败: " + e.getMessage());
        }
    }
    
    @Override
    public Result getHotelReviewStats(String hotelId) {
        try {
            // 获取酒店评论统计信息
            Map<String, Object> stats = reviewMapper.getReviewStats(Long.valueOf(hotelId));
            
            if (stats == null) {
                // 如果没有评论，返回默认值
                Map<String, Object> defaultStats = new HashMap<>();
                defaultStats.put("totalReviews", 0);
                defaultStats.put("averageRating", 0.0);
                defaultStats.put("ratingDistribution", Map.of(
                    "5", 0,
                    "4", 0,
                    "3", 0,
                    "2", 0,
                    "1", 0
                ));
                return Result.success(defaultStats);
            }
            
            // 从查询结果中获取数据
            Long totalReviews = ((Number) stats.getOrDefault("total_reviews", 0)).longValue();
            Double avgRating = ((Number) stats.getOrDefault("avg_rating", 0.0)).doubleValue();
            
            // 格式化成前端所需数据结构
            Map<String, Object> formattedStats = new HashMap<>();
            formattedStats.put("totalReviews", totalReviews);
            formattedStats.put("averageRating", avgRating);
            
            // 评分分布
            Map<String, Integer> ratingDistribution = new HashMap<>();
            ratingDistribution.put("5", ((Number) stats.getOrDefault("rating_5", 0)).intValue());
            ratingDistribution.put("4", ((Number) stats.getOrDefault("rating_4", 0)).intValue());
            ratingDistribution.put("3", ((Number) stats.getOrDefault("rating_3", 0)).intValue());
            ratingDistribution.put("2", ((Number) stats.getOrDefault("rating_2", 0)).intValue());
            ratingDistribution.put("1", ((Number) stats.getOrDefault("rating_1", 0)).intValue());
            formattedStats.put("ratingDistribution", ratingDistribution);
            
            return Result.success(formattedStats);
        } catch (Exception e) {
            log.error("获取酒店评论统计信息失败", e);
            return Result.error("获取酒店评论统计信息失败: " + e.getMessage());
        }
    }
    
    @Override
    public Result getHotelReviewsForAdmin(String hotelId, String adminId, Integer rating, Integer status, String startDate, String endDate, int page, int pageSize) {
        try {
            // 验证管理员对该酒店的管理权限
            if (!verifyAdminHotelAccess(adminId, hotelId)) {
                return Result.error("您没有权限管理该酒店的评论");
            }
            
            // 分页查询
            Page<Map<String, Object>> pageParam = new Page<>(page, pageSize);
            IPage<Map<String, Object>> result = reviewMapper.getHotelReviewsPage(
                pageParam, 
                Long.valueOf(hotelId), 
                rating, 
                status, 
                startDate, 
                endDate
            );
            
            // 转换为ReviewVO
            List<ReviewVO> reviews = new ArrayList<>();
            for (Map<String, Object> record : result.getRecords()) {
                ReviewVO vo = new ReviewVO();
                vo.setId((Long) record.get("review_id"));
                vo.setBookingId((Long) record.get("booking_id"));
                vo.setHotelId((Long) record.get("hotel_id"));
                vo.setUserId((Long) record.get("user_id"));
                vo.setUserName((String) record.get("user_name"));
                vo.setUserAvatar((String) record.get("user_avatar"));
                vo.setRating((Integer) record.get("rating"));
                vo.setContent((String) record.get("content"));
                
                // 处理照片
                String photos = (String) record.get("photos");
                if (photos != null && !photos.isEmpty()) {
                    try {
                        vo.setPhotos(objectMapper.readValue(photos, List.class));
                    } catch (Exception e) {
                        log.error("解析照片失败: {}", e.getMessage());
                        vo.setPhotos(Collections.emptyList());
                    }
                }
                
                // 处理标签
                String tags = (String) record.get("tags");
                if (tags != null && !tags.isEmpty()) {
                    try {
                        vo.setTags(objectMapper.readValue(tags, List.class));
                    } catch (Exception e) {
                        log.error("解析标签失败: {}", e.getMessage());
                        vo.setTags(Collections.emptyList());
                    }
                }
                
                // 处理回复
                vo.setReply((String) record.get("reply"));
                LocalDateTime replyTime = (LocalDateTime) record.get("reply_time");
                if (replyTime != null) {
                    vo.setReplyTime(replyTime);
                    vo.setReplyDate(replyTime.format(DATE_FORMATTER));
                }
                
                // 处理创建时间
                LocalDateTime createdAt = (LocalDateTime) record.get("created_at");
                vo.setCreatedAt(createdAt);
                vo.setDate(createdAt.format(DATE_FORMATTER));
                
                // 设置状态
                Integer reviewStatus = (Integer) record.get("status");
                vo.setStatus(ReviewVO.getStatusString(reviewStatus));
                
                reviews.add(vo);
            }
            
            // 构建分页结果
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("records", reviews);
            resultMap.put("total", result.getTotal());
            resultMap.put("pages", result.getPages());
            resultMap.put("current", result.getCurrent());
            resultMap.put("size", result.getSize());
            
            return Result.success(resultMap);
        } catch (Exception e) {
            log.error("管理员获取酒店评论列表失败", e);
            return Result.error("获取酒店评论列表失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public Result replyReview(String reviewId, String adminId, String reply) {
        try {
            // 获取评论
            LambdaQueryWrapper<Review> rqw = new LambdaQueryWrapper<>();
            rqw.eq(Review::getReviewId, reviewId);

            Review review = getOne(rqw);
            if (review == null) {
                return Result.error("评论不存在");
            }
            
            // 验证管理员对该酒店的管理权限
            if (!verifyAdminHotelAccess(adminId, review.getHotelId().toString())) {
                return Result.error("您没有权限回复该酒店的评论");
            }
            
            // 更新评论回复
            int rows = reviewMapper.updateReviewReply(review.getReviewId(), reply);
            if (rows > 0) {
                return Result.success("回复成功");
            } else {
                return Result.error("回复失败");
            }
        } catch (Exception e) {
            log.error("回复评论失败", e);
            return Result.error("回复评论失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public Result updateReviewStatus(String reviewId, String adminId, Integer status) {
        try {
            // 获取评论
            Review review = reviewMapper.selectById(reviewId);
            if (review == null) {
                return Result.error("评论不存在");
            }
            
            // 验证管理员对该酒店的管理权限
            if (!verifyAdminHotelAccess(adminId, review.getHotelId().toString())) {
                return Result.error("您没有权限管理该酒店的评论");
            }
            
            // 更新评论状态
            int rows = reviewMapper.updateReviewStatus(review.getReviewId(), status);
            if (rows > 0) {
                String statusStr = ReviewVO.getStatusString(status);
                return Result.success("评论状态已更新为" + statusStr);
            } else {
                return Result.error("更新评论状态失败");
            }
        } catch (Exception e) {
            log.error("更新评论状态失败", e);
            return Result.error("更新评论状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 验证管理员是否有权限管理指定酒店
     * @param adminId 管理员ID
     * @param hotelId 酒店ID
     * @return 是否有权限
     */
    private boolean verifyAdminHotelAccess(String adminId, String hotelId) {
        // TODO: 实现管理员对酒店的权限校验
        // 通常需要查询管理员与酒店的关系表，验证管理员是否可以管理该酒店
        // 为简化处理，这里暂时返回true，表示所有管理员都有权限
        return true;
    }
    
    /**
     * 生成评论ID
     * @return 评论ID
     */
    private Long generateReviewId() {
        // 生成评论ID：当前时间戳 + 4位随机数
        long timestamp = System.currentTimeMillis();
        int random = new Random().nextInt(10000);
        return Long.valueOf(timestamp + "" + String.format("%04d", random));
    }
    
    /**
     * 根据评论内容和评分自动生成标签
     * @param reviewDTO 评论数据
     * @return 标签列表
     */
    private List<String> generateTags(ReviewDTO reviewDTO) {
        List<String> tags = new ArrayList<>();
        
        // 基于评分添加标签
        int rating = reviewDTO.getRating();
        if (rating >= 4) {
            tags.add("好评");
            if (rating == 5) {
                tags.add("超赞体验");
            }
        } else if (rating <= 2) {
            tags.add("有待改进");
        }
        
        // 基于评论内容添加标签
        String content = reviewDTO.getContent().toLowerCase();
        if (content.contains("干净") || content.contains("整洁")) {
            tags.add("干净整洁");
        }
        if (content.contains("服务") && (content.contains("好") || content.contains("棒") || content.contains("热情"))) {
            tags.add("服务好");
        }
        if (content.contains("位置") && (content.contains("好") || content.contains("便利") || content.contains("方便"))) {
            tags.add("位置好");
        }
        if (content.contains("价格") && (content.contains("高") || content.contains("贵"))) {
            tags.add("性价比低");
        }
        if (content.contains("价格") && (content.contains("合理") || content.contains("实惠") || content.contains("值"))) {
            tags.add("性价比高");
        }
        
        // 如果有房型信息，也可以添加
        if (reviewDTO.getRoomType() != null && !reviewDTO.getRoomType().isEmpty()) {
            tags.add(reviewDTO.getRoomType());
        }
        
        return tags;
    }
    
    /**
     * 将Review实体转换为ReviewVO
     * @param review Review实体
     * @return ReviewVO
     */
    private ReviewVO convertToReviewVO(Review review) {
        ReviewVO vo = new ReviewVO();
        vo.setId(review.getReviewId());
        vo.setBookingId(review.getBookingId());
        vo.setHotelId(review.getHotelId());
        vo.setUserId(review.getUserId());
        vo.setRating(review.getRating());
        vo.setContent(review.getContent());
        
        // 处理照片
        if (review.getPhotos() != null && !review.getPhotos().isEmpty()) {
            try {
                vo.setPhotos(objectMapper.readValue(review.getPhotos(), List.class));
            } catch (Exception e) {
                log.error("解析照片失败: {}", e.getMessage());
                vo.setPhotos(Collections.emptyList());
            }
        }
        
        // 处理标签
        if (review.getTags() != null && !review.getTags().isEmpty()) {
            try {
                vo.setTags(objectMapper.readValue(review.getTags(), List.class));
            } catch (Exception e) {
                log.error("解析标签失败: {}", e.getMessage());
                vo.setTags(Collections.emptyList());
            }
        }
        
        // 处理回复
        vo.setReply(review.getReply());
        if (review.getReplyTime() != null) {
            vo.setReplyTime(review.getReplyTime());
            vo.setReplyDate(review.getReplyTime().format(DATE_FORMATTER));
        }
        
        // 处理创建时间
        vo.setCreatedAt(review.getCreatedAt());
        vo.setDate(review.getCreatedAt().format(DATE_FORMATTER));
        
        // 设置状态
        vo.setStatus(ReviewVO.getStatusString(review.getStatus()));
        
        return vo;
    }
} 